﻿using System;
using System.Collections.Generic;
using UnityEngine;

public class MapManager : MonoSingleton<MapManager>
{
    /// <summary>
    /// 宽度 像素
    /// </summary>
    private const float fCellX = 0.8f;

    /// <summary>
    /// 高度 像素
    /// </summary>
    private const float fCellY = 0.8f;

    private const float fPlayerX = 0.7f;
    private const float fPlayerY = 0.7f;

    private MapNode[] mCells;

    private GameObject goModel;

    private MapConfigSheet mapConfig;

    private uint iPlayerIdx = 0;
    public override void Initialize()
    {
        base.Initialize();
        if (goModel == null)
        {
            goModel = GameObject.Instantiate(Resources.Load<GameObject>("Map/MapNode"));
            goModel.SetActive(false);
        }
    }

    public override void Release()
    {
        if (mCells != null)
        {
            for (int i = 0; i < mCells.Length; i++)
            {
                mCells[i].Release();
            }

            mCells = null;
        }
        
        base.Release();
    }

    public void Clear()
    {
        iCurrIdY = -1;
        iCurrIdX = -1;
    }

    public bool IsMove(float x, float y, MoveDir dir)
    {
        int iCurrCell = GetCell(x, y);

        int iNextCell = iCurrCell;

        if (dir == MoveDir.Down)
        {
            iNextCell -= (int)mapConfig.MaxWidth;
        }
        else if (dir == MoveDir.Up)
        {
            iNextCell += (int)mapConfig.MaxWidth;
        }
        else if (dir == MoveDir.Left)
        {
            iNextCell--;
        }
        else if (dir == MoveDir.Right)
        {
            iNextCell++;
        }

        if (iNextCell < 0 || iNextCell >= mapConfig.Map.Length)
        {
            iNextCell = iCurrCell;
        }

        if (mapConfig.Map[iNextCell] == 0)
        {
            MapNode node = mCells[iNextCell];

            bool move = true;
            switch (dir)
            {
                case MoveDir.Down:
                    if (y < node.Y + fCellY)
                    {
                        move = false;
                    }
                    break;
                case MoveDir.Up:
                    if (y + fPlayerY > node.Y)
                    {
                        move = false;
                    }
                    break;
                case MoveDir.Left:
                    if (x < node.X + fCellX)
                    {
                        move = false;
                    }
                    break;
                case MoveDir.Right:
                    if (x + fPlayerX > node.X)
                    {
                        move = false;
                    }
                    break;
            }

            return move;
        }

        return true;
    }
    public bool IsOut(float x, float y)
    {
        float moveX = x;
        float moveY = y;
        float fLeft = 0;
        float fRight =( mapConfig.MaxWidth - 1) * fCellX;
        float fUp = (mapConfig.MaxHeight- 1) * fCellY;
        float fDown = 0;

        if (moveX < fLeft)
        {
            return true;
        }

        if (moveX > fRight)
        {
            return true;
        }

        if (moveY > fUp)
        {
            return true;
        }

        if (moveY < fDown)
        {
            return true;
        }

        return false;
    }

    public Vector2 MoveNextPoint(float x, float y,MoveDir dir)
    {
        int iCurrCell = GetCell(x, y);

        float fCurrCellX = x / fCellX;
        float fCurrCellY = y / fCellY;

        int iCellX = (int)(fCurrCellX);
        int iCellY = (int)(fCurrCellY);

        int iNextCellX = iCellX;
        int iNextCellY = iCellY;

        int idx = 0;
        if (x > iCellX * fCellX)
        {
            iNextCellX++;
        }
        else if (x < iCellX * fCellX)
        {
            iNextCellX--;
        }

        if (y > iCellY * fCellY)
        {
            iNextCellY++;
        }else if (y < iCellY * fCellY)
        {
            iNextCellY--;
        }

        idx = iCellX + iCellY * (int)mapConfig.MaxWidth;
        if (mapConfig.Map[idx] != 0)
        {
            return  new Vector2(iNextCellX * fCellX, iNextCellY * fCellY);
        }

        return new Vector2(iCellX * fCellX, iCellY * fCellY);
    }

   public bool DirMove(float x, float y,MoveDir dir)
    {
        int idx = GetCell(x, y);

        switch (dir)
        {
            case MoveDir.Down:
                idx-= (int)mapConfig.MaxWidth;
                break;
            case MoveDir.Up:
                idx += (int)mapConfig.MaxWidth;
                break;
            case MoveDir.Left:
                idx--;
                break;
            case MoveDir.Right:
                idx++;
                break;
        }

        if (idx >= 0 && idx < mapConfig.Map.Length)
        {
            if (mapConfig.Map[idx] != 0)
            {
                return true;
            }
        }

        return false;
    }

   public int GetNextCell(float x, float y,MoveDir dir)
   {
       int iCurrCell = GetCell(x, y);
       int iNextCell = iCurrCell;

       if (iCurrCell < 0 || iCurrCell > mapConfig.Map.Length - 1)
       {
           return -1;
       }

       MapNode  mapNode = mCells[iCurrCell];
       if (dir == MoveDir.Down)
       {
           if (y < mapNode.Y + fCellY)
           {
               iNextCell -= (int)mapConfig.MaxWidth;
           }
       }
       else if (dir == MoveDir.Up)
       {
           iNextCell += (int)mapConfig.MaxWidth;
       }
       else if (dir == MoveDir.Left)
       {
           iNextCell--;
       }
       else if (dir == MoveDir.Right)
       {
           iNextCell++;
       }

       return iNextCell;
   }

   public uint GetMaxY()
   {
       return mapConfig.MaxHeight;
   }

   public uint GetMaxX()
   {
       return mapConfig.MaxWidth;
   }

   public float GetXToPos(int x)
   {
       return x * fCellX;
   }
   public float GetYToPos(int y)
   {
       return y * fCellX;
   }

   public bool IsWall(int x, int y)
   {
       int idx = x + y * (int)mapConfig.MaxWidth;
       if (mapConfig.Map[idx] == 0) return true;
       return false;
   }

    public int GetCell(float x, float y)
    {
        float fCurrCellX = x / fCellX;
        float fCurrCellY = y / fCellY;

        int iCellX = (int)(fCurrCellX);
        int iCellY = (int)(fCurrCellY);

        int idx = iCellX + iCellY * (int)mapConfig.MaxWidth;

        return idx;
    }

    private int iCurrIdX = -1;
    private int iCurrIdY = -1;
    public int GetCurrIdx()
    {
        if (iCurrIdX == -1 || iCurrIdY == -1) return 0;

            int idx = iCurrIdX + iCurrIdY * (int)mapConfig.MaxWidth;
        return mCells[idx].iType;
    }

    /// <summary>
    /// 获取碎片
    /// </summary>
    /// <returns></returns>
    public bool GetChip(int x, int y)
    {
        int idx = x + y * (int)mapConfig.MaxWidth;
        MapNode mapNode = mCells[idx];
        iCurrIdX = x;
        iCurrIdY = y;

        if (mapNode.iType >= 5 && mapNode.iType < 20)
        {
            int iWallIndex = RandomHelper.Range(1, 3);
            mapNode.iType = iWallIndex;
            mapNode.SetSprite(SpriteManager.Instance.LoadSpriteAtlas("MapAtlas", iWallIndex.ToString()));

            return true;
        }

        return false;
    }

    public Vector2 GetPlayerCell()
    {
        uint PosX = iPlayerIdx % mapConfig.MaxWidth;
        uint PosY = iPlayerIdx / mapConfig.MaxWidth;

        return new Vector2(PosX,PosY);
    }

    public void CreateMap(uint mapID)
    {
        mapConfig = MapConfigSheet.Get(mapID);

        if (mapConfig == null) return;

        mCells = new MapNode[mapConfig.MaxWidth * mapConfig.MaxHeight];

        int x = 0;
        int y = 0;
        for (int i = 0; i < mapConfig.Map.Length; i++)
        {
            MapNode mapNode = new MapNode();
            mCells[i] = mapNode;

            GameObject go = GameObject.Instantiate(goModel);
            mapNode.Init(go);
            mapNode.SetParent(this.transform);


            if (mapConfig.Map[i] == 0)
            {
                int iWallIndex = RandomHelper.Range(1, 4);
                mapNode.SetSprite(SpriteManager.Instance.LoadSpriteAtlas("MapAtlas", "0_" + iWallIndex));
            }
            else
            {
                if (mapConfig.Map[i] == 20)
                {
                    iPlayerIdx = (uint)i;
                    mapNode.SetSprite(SpriteManager.Instance.LoadSpriteAtlas("MapAtlas", 1.ToString()));

                }
                else
                {
                    mapNode.SetSprite(SpriteManager.Instance.LoadSpriteAtlas("MapAtlas", mapConfig.Map[i].ToString()));
                }

            }

            mapNode.iType = mapConfig.Map[i];

            mapNode.SetXY(x * fCellX, y * fCellY);
            mapNode.SetActive(true);
            x++;
            if (x >= mapConfig.MaxWidth)
            {
                x = 0;
                y++;
            }
        }
    }
}
